HAL SPDIFRX Typical use cases for migration

This section provides information about the HAL SPDIFRX Typical use cases for migration.

The HAL SPDIFRX receive data and receive control APIs are almost the same between HAL1 and HAL2. The only differences are:

  • The naming changes are as follows: HAL1 uses HAL_SPDIFRX_ReceiveDataFlow() and HAL_SPDIFRX_ReceiveCtrlFlow() (also available as HAL_SPDIFRX_ReceiveControlFlow() in some series), while HAL2 uses HAL_SPDIFRX_ReceiveData() and HAL_SPDIFRX_ReceiveCtrl(), respectively.

  • The data buffer is now passed as a pointer to void instead of a pointer to a specific data type. This allows the user to pass any data type without needing to cast at the application level.

  • The processes for receiving data and control using polling, interrupts or DMA are the same in HAL1 and HAL2.

Use case: HAL SPDIFRX receptions in polling mode

Sequence diagram

HAL1

HAL2

SPDIFRX receptions in polling mode

 @startuml
 hide footbox
 participant "User Application" as p1
 participant "<font color=green><b>HAL SPDIFRX</b></font>" as p2

 group Initialization
   p1->p2: HAL_SPDIFRX_Init(&hSPDIFRX1)
 end

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 group SPDIFRX HAL Data reception in polling mode
   p1->p2: HAL_SPDIFRX_ReceiveDataFlow(&hSPDIFRX1,\n                              pDataBuffer,\n                              DATA_SIZE,\n                              1000)
   note over p2 #00FF00
   Receiving data ongoing
   end note
   p2-->p1: <color #Green> HAL_OK
 end

group SPDIFRX HAL Control reception in polling mode
  p1->p2: HAL_SPDIFRX_ReceiveControlFlow(&hSPDIFRX1,\n                           pCtrlBuffer,\n                           CTRL_SIZE,\n                           1000)
  note over p2 #00FF00
  Receiving control information ongoing
  end note
  p2-->p1: <color #Green> HAL_OK
end

@enduml

SPDIFRX receptions in polling mode

@startuml
hide footbox
participant "User Application" as p1
participant "<font color=green><b>HAL SPDIFRX</b></font>" as p2

group Initialization
 p1->p2: HAL_SPDIFRX_Init(&hSPDIFRX1,\n                                     HAL_SPDIFRX1)
end

group Mandatory configuration
 p1->p2: HAL_SPDIFRX_SetConfig(&hSPDIFRX1,\n                                            &spdifrx_config)
end
group Optional configuration
 p1->p2: HAL_SPDIFRX_SetSynchroRetries(&hSPDIFRX1,\n                                                      HAL_SPDIFRX_SYNCHRO_RETRIES_3)
 p1->p2: HAL_SPDIFRX_SetControlChannel(&hSPDIFRX1,\n                                                      HAL_SPDIFRX_CONTROL_CHANNEL_A)
 p1->p2: HAL_SPDIFRX_EnableWaitForActivity(&hSPDIFRX1)
 p1->p2: HAL_SPDIFRX_EnableAlignmentForStereoOverrun(&hSPDIFRX1)
 p1->p2: HAL_SPDIFRX_SetMasks(&hSPDIFRX1,\n                                           &mask)
 p1->p2: HAL_SPDIFRX_DisableSymbolClock(&hSPDIFRX1)
end

group SPDIFRX HAL Data reception in polling mode
  p1->p2: HAL_SPDIFRX_ReceiveData(&hSPDIFRX1,\n                                                        pDataBuffer,\n                                                        DATA_SIZE,\n                                                        1000)
  note over p2 #00FF00
  Receiving data ongoing
  end note
  p2-->p1: <color #Green> HAL_OK
end

group SPDIFRX HAL Control reception in polling mode
  p1->p2: HAL_SPDIFRX_ReceiveCtrl(&hSPDIFRX1,\n                                                           pCtrlBuffer,\n                                                        CTRL_SIZE,\n                                                        1000)
  note over p2 #00FF00
  Receiving control information ongoing
  end note
  p2-->p1: <color #Green> HAL_OK
end

@enduml

Code snippet

HAL1

HAL2

#define SPDIFRX_DATA_SIZE   384
#define SPDIFRX_CTRL_SIZE   24

uint32_t SpdifRxDataBuffer[SPDIFRX_DATA_SIZE];
uint32_t SpdifRxCtrlBuffer[SPDIFRX_CTRL_SIZE];
SPDIFRX_HandleTypeDef hSPDIFRX1;



/* Enable the SPDIFRX clock and configure its
   clock source using the HAL RCC driver
*/

hSPDIFRX1.Instance = SPDIFRX;
hSPDIFRX1.Init.InputSelection = SPDIFRX_INPUT_IN0;
hSPDIFRX1.Init.DataFormat = SPDIFRX_DATAFORMAT_MSB;





hSPDIFRX1.Init.PreambleTypeMask = SPDIFRX_PREAMBLETYPEMASK_ON;
hSPDIFRX1.Init.ChannelStatusMask = SPDIFRX_CHANNELSTATUS_ON;
hSPDIFRX1.Init.ValidityBitMask = SPDIFRX_VALIDITYMASK_OFF;
hSPDIFRX1.Init.ParityErrorMask = SPDIFRX_PARITYERRORMASK_OFF;

hSPDIFRX1.Init.Retries = SPDIFRX_MAXRETRIES_15;
hSPDIFRX1.Init.ChannelSelection = SPDIFRX_CHANNEL_A;
hSPDIFRX1.Init.StereoMode = SPDIFRX_STEREOMODE_ENABLE;
hSPDIFRX1.Init.WaitForActivity = SPDIFRX_WAITFORACTIVITY_ON;
hSPDIFRX1.Init.SymbolClockGen = ENABLE;
hSPDIFRX1.Init.BackupSymbolClockGen = ENABLE;
HAL_SPDIFRX_Init(&hSPDIFRX1);


/* Ensure that GPIO of SPDIFRX is
   configured properly
/*
...
*/

/* Receive data */
if (HAL_SPDIFRX_ReceiveDataFlow(&hSPDIFRX1,
                                (uint32_t *)SpdifRxDataBuffer,
                                SPDIFRX_DATA_SIZE,
                                1000) != HAL_OK)

/* Receive control */
if (HAL_SPDIFRX_ReceiveCtrlFlow(&hSPDIFRX1,
                                (uint32_t *)SpdifRxCtrlBuffer,
                                SPDIFRX_CTRL_SIZE,
                                1000) != HAL_OK)
#define SPDIFRX_DATA_SIZE  384
#define SPDIFRX_CTRL_SIZE  24

uint32_t SpdifRxDataBuffer[SPDIFRX_DATA_SIZE];
uint32_t SpdifRxCtrlBuffer[SPDIFRX_CTRL_SIZE];
hal_spdifrx_config_t spdifrx_config;
hal_spdifrx_masks_t  spdifrx_mask;
hal_spdifrx_handle_t hSPDIFRX1;

/* Enable the SPDIFRX clock and configure its
   clock source using the HAL RCC driver
*/

HAL_SPDIFRX_Init(&hSPDIFRX1, HAL_SPDIFRX1);
spdifrx_config.input_selection = HAL_SPDIFRX_INPUT_0;
spdifrx_config.data_format     = HAL_SPDIFRX_DATA_FORMAT_MSB;
HAL_SPDIFRX_SetConfig(&hSPDIFRX1,&spdifrx_config);

/* Additional optional configuration
   feature when needed
*/
spdifrx_mask.preamble_mask     = HAL_SPDIFRX_PREAMBLE_MASK_ENABLE;
spdifrx_mask.channel_user_mask = HAL_SPDIFRX_CHANNEL_USER_MASK_ENABLE;
spdifrx_mask.validity_mask     = HAL_SPDIFRX_VALIDITY_MASK_DISABLE;
spdifrx_mask.parity_error_mask = HAL_SPDIFRX_PARITY_ERROR_MASK_DISABLE;
HAL_SPDIFRX_SetMasks(&hSPDIFRX1,&spdifrx_mask);
HAL_SPDIFRX_SetSynchroRetries(&hSPDIFRX1,HAL_SPDIFRX_SYNCHRO_RETRIES_15);
HAL_SPDIFRX_SetControlChannel(&hSPDIFRX1,HAL_SPDIFRX_CONTROL_CHANNEL_A);
HAL_SPDIFRX_EnableAlignmentForStereoOverrun(&hSPDIFRX1);
HAL_SPDIFRX_EnableWaitForActivity(&hSPDIFRX1);
HAL_SPDIFRX_EnableSymbolClock(&hSPDIFRX1,HAL_SPDIFRX_BACKUP_SYMBOL_CLK_ENABLED);



/* Ensure that GPIO of SPDIFRX is
   configured properly
/*
...
*/


/* Receive data */
if (HAL_SPDIFRX_ReceiveData(&hSPDIFRX1,
                            (uint32_t *)SpdifRxDataBuffer,
                            SPDIFRX_DATA_SIZE,
                            1000) != HAL_OK)

/* Receive control */
if (HAL_SPDIFRX_ReceiveCtrl(&hSPDIFRX1,
                            (uint32_t *)SpdifRxCtrlBuffer,
                            SPDIFRX_CTRL_SIZE,
                            1000) != HAL_OK)

Use case: HAL SPDIFRX receptions in interrupt mode

Note

The following sequence diagrams describe the processing APIs in interrupt mode. The configuration part has already been described in the polling use case above.

Sequence diagram

HAL1

HAL2

SPDIFRX HAL Receive IT

@startuml
hide footbox
participant "User Application" as p1
participant "<font color=green><b>HAL SPDIFRX</b></font>" as p2
participant "SPDIFRX_IRQHandler" as p3
participant "Hardware" as p5

group SPDIFRX HAL Data reception in interrupt mode
  p1->p2: HAL_SPDIFRX_ReceiveDataFlow_IT(&hSPDIFRX1,\n                                          pDataBuffer,\n                                          DATA_SIZE)
  note over p2 #00FF00
  Receiving data channel ongoing
  end note

  p5-->p3: SPDIFRX data interrupt
  p3->p2: HAL_SPDIFRX_IRQHandler(&hSPDIFRX1)
  note over p2 #FFFF99
  Data flow reception
  end note
  note over p2 #00FF00
  End of receiving data channel
  end note
  p2->p1: HAL_SPDIFRX_RxCpltCallback(&hSPDIFRX1)
end

group SPDIFRX HAL Control reception in interrupt mode
  p1->p2: HAL_SPDIFRX_ReceiveCtrlFlow_IT(&hSPDIFRX1,\n                                          pCtrlBuffer,\n                                          CTRL_SIZE)
  note over p2 #00FF00
  Receiving control channel ongoing
  end note

  p5-->p3: SPDIFRX control interrupt
  p3->p2: HAL_SPDIFRX_IRQHandler(&hSPDIFRX1)
  note over p2 #FFFF99
  Control flow reception
  end note
  note over p2 #00FF00
  End of receiving control channel
  end note
  p2->p1: HAL_SPDIFRX_CxCpltCallback(&hSPDIFRX1)
end

@enduml

SPDIFRX HAL Receive IT

@startuml
hide footbox
participant "User Application" as p1
participant "<font color=green><b>HAL SPDIFRX</b></font>" as p2
participant "SPDIFRX_IRQHandler" as p3
participant "Hardware" as p5

group SPDIFRX HAL Data reception in interrupt mode
  p1->p2: HAL_SPDIFRX_ReceiveData_IT(&hSPDIFRX1,\n                           pDataBuffer,\n                           DATA_SIZE)
  note over p2 #00FF00
  Receiving data channel ongoing
  end note

  p5-->p3: SPDIFRX data interrupt
  p3->p2: HAL_SPDIFRX_IRQHandler(&hSPDIFRX1)
  note over p2 #FFFF99
  Data flow reception
  end note
  note over p2 #00FF00
  End of receiving data channel
  end note
  p2->p1: HAL_SPDIFRX_DataCpltCallback(&hSPDIFRX1)
end

group SPDIFRX HAL Control reception in interrupt mode
  p1->p2: HAL_SPDIFRX_ReceiveCtrl_IT(&hSPDIFRX1,\n                           pCtrlBuffer,\n                           CTRL_SIZE)
  note over p2 #00FF00
  Receiving control channel ongoing
  end note

  p5-->p3: SPDIFRX control interrupt
  p3->p2: HAL_SPDIFRX_IRQHandler(&hSPDIFRX1)
  note over p2 #FFFF99
  Control flow reception
  end note
  note over p2 #00FF00
  End of receiving control channel
  end note
  p2->p1: HAL_SPDIFRX_ControlCpltCallback(&hSPDIFRX1)
end

@enduml

Code snippet

HAL1

HAL2

#define SPDIFRX_DATA_SIZE   384
#define SPDIFRX_CTRL_SIZE   24

uint32_t SpdifRxBuffer[SPDIFRX_DATA_SIZE];
uint32_t SpdifCxBuffer[SPDIFRX_CTRL_SIZE];
SPDIFRX_HandleTypeDef hSPDIFRX1;

/* Ensure that all required peripherals
   (SPDIFRX1, GPIO, etc.) are configured properly
/*
...
*/

/* Peripheral interrupt init */


/* Start data and control reception in interruption mode */
HAL_SPDIFRX_ReceiveDataFlow_IT(&hSPDIFRX1,
                               (uint32_t *) SpdifRxBuffer,
                               SPDIFRX_DATA_SIZE);

HAL_SPDIFRX_ReceiveCtrlFlow_IT(&hSPDIFRX1,
                               (uint32_t *) SpdifCxBuffer,
                               SPDIFRX_CTRL_SIZE);

/* Ensure that HAL_SPDIFRX_IRQHandler() is called for the appropriate SPDIFRX
   instance within the corresponding ISR handlers according to the product.
*/

/* SPDIFRX1 data complete callback */
void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hSPDIFRX1)
{
   data_cpt_occurred = 1;
}

/* SPDIFRX1 control complete callback */
void HAL_SPDIFRX_CxCpltCallback(SPDIFRX_HandleTypeDef *hSPDIFRX1)
{
   ctrl_cpt_occurred = 1;
}
#define SPDIFRX_DATA_SIZE  384
#define SPDIFRX_CTRL_SIZE  24

uint32_t SpdifRxBuffer[SPDIFRX_DATA_SIZE];
uint32_t SpdifCxBuffer[SPDIFRX_CTRL_SIZE];
hal_spdifrx_handle_t hSPDIFRX1;

/* Ensure that all required peripherals
   (SPDIFRX1, GPIO etc.) are configured properly
/*
...
*/

/* Enable the SPDIFRX event interrupt
   using the HAL CORTEX driver */

/* Start data and control reception in interruption mode */
HAL_SPDIFRX_ReceiveData_IT(&hSPDIFRX1,
                           (uint32_t *) SpdifRxBuffer,
                           SPDIFRX_DATA_SIZE);

HAL_SPDIFRX_ReceiveCtrl_IT(&hSPDIFRX1,
                           (uint32_t *) SpdifCxBuffer,
                           SPDIFRX_CTRL_SIZE);

/* Ensure that HAL_SPDIFRX_IRQHandler() is called for the required instance
   within the corresponding ISR handlers according to the product.
*/

/* SPDIFRX1 data complete callback */
void HAL_SPDIFRX_DataCpltCallback(hal_spdifrx_handle_t *hSPDIFRX1)
{
  data_cpt_occurred = 1;
}

/* SPDIFRX1 control complete callback */
void HAL_SPDIFRX_ControlCpltCallback(hal_spdifrx_handle_t *hSPDIFRX1)
{
   ctrl_cpt_occurred = 1;
}

Use case: HAL SPDIFRX data flow reception in DMA mode

Note

The following sequence diagrams describe the processing APIs for data reception in DMA mode. The configuration part has already been described in the polling use case above.

Sequence diagram

SPDIFRX HAL Receive data DMA

@startuml
hide footbox
participant "User Application" as p1
participant "<font color=green><b>HAL SPDIFRX</b></font>" as p2
participant "DMA" as p3
participant "NVIC" as p5
participant "Hardware" as p4

group Link DMA
  p1->p2: __HAL_LINKDMA(&hSPDIFRX1,\n                             hdma_data,\n                             hdma_spdif_rx_dt)
end

group Start data DMA reception
  p1->p2: HAL_SPDIFRX_ReceiveDataFlow_DMA(&hSPDIFRX1,\n                                             pDataBuffer,\n                                             DATA_SIZE)
  p2->p3: HAL_DMA_Start_IT(hdma_data,\n                          src_addr, dest_addr,\n                          size)
end

group Data DMA complete
  p4-->p5: DMAx data complete interrupt
  p5->p3: HAL_DMA_IRQHandler(&hdma_spdif_rx_dt)
  p3->p2: XferCpltCallback()
  p2->p1: HAL_SPDIFRX_RxCpltCallback(&hSPDIFRX1)
  note over p1 #00FF00
  All data words have been received
  end note
end

group Stop the audio stream receive
  p1->p2: HAL_SPDIFRX_DMAStop(&hSPDIFRX1)
end

@enduml

Code snippet

HAL1

HAL2

#define SPDIFRX_DATA_SIZE   384

uint32_t SpdifRxBuffer[SPDIFRX_DATA_SIZE];
SPDIFRX_HandleTypeDef hSPDIFRX1;
DMA_NodeConfTypeDef NodeConfig;
DMA_NodeTypeDef Node_GPDMA1_Channel1;
DMA_QListTypeDef List_GPDMA1_Channel1;
DMA_HandleTypeDef handle_GPDMA1_Channel1;

volatile uint32_t data_cpt_occurred = 0U;

/* Ensure that all required peripherals
   (SPDIFRX, GPIO, DMA Clock etc...) are configured properly
/*
...
*/

NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_SPDIF_RX_DT;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel1)

HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel1, NULL, &Node_GPDMA1_Channel1)

HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel1)

handle_GPDMA1_Channel1.Instance = GPDMA1_Channel1;
handle_GPDMA1_Channel1.InitLinkedList.Priority = DMA_HIGH_PRIORITY;
handle_GPDMA1_Channel1.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel1.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel1.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel1.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
HAL_DMAEx_List_Init(&handle_GPDMA1_Channel1)

HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &List_GPDMA1_Channel1)


__HAL_LINKDMA(hspdifrx, hdmaDrRx, handle_GPDMA1_Channel1);


/* Start data reception in DMA mode */
HAL_SPDIFRX_ReceiveDataFlow_DMA(&hSPDIFRX1,
                                (uint32_t *) SpdifRxBuffer,
                                SPDIFRX_DATA_SIZE);

/* Stop the audio stream receive */
HAL_SPDIFRX_DMAStop(&hSPDIFRX1);

/* Check the exact name of the SPDIFRX data
   DMA IRQ handler in the device startup file. */

/* SPDIFRX data complete callback */
void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hSPDIFRX1)
{
   data_cpt_occurred = 1;
}
#define SPDIFRX_DATA_SIZE   384

uint32_t SpdifRxBuffer[SPDIFRX_DATA_SIZE];
hal_spdifrx_handle_t hSPDIFRX1;
hal_dma_handle_t hGPDMA1_CH1;
hal_dma_node_t DMA_Node_SPDIFRX1_DT;



volatile uint32_t data_cpt_occurred = 0U;

/* Ensure that all required peripherals
   (SPDIFRX, GPIO, NVIC, DMA Clock etc...) are configured properly
/*
...
*/

HAL_DMA_Init(&hGPDMA1_CH1, HAL_GPDMA1_CH1);

hal_dma_direct_xfer_config_t xfer_cfg_spdifrx1_dt_dma;
xfer_cfg_spdifrx1_dt_dma.request         = HAL_GPDMA1_REQUEST_SPDIFRX1_DT;
xfer_cfg_spdifrx1_dt_dma.direction       = HAL_DMA_DIRECTION_PERIPH_TO_MEMORY;
xfer_cfg_spdifrx1_dt_dma.src_inc         = HAL_DMA_SRC_ADDR_FIXED;
xfer_cfg_spdifrx1_dt_dma.dest_inc        = HAL_DMA_DEST_ADDR_INCREMENTED;
xfer_cfg_spdifrx1_dt_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_WORD;
xfer_cfg_spdifrx1_dt_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_WORD;
xfer_cfg_spdifrx1_dt_dma.priority        = HAL_DMA_PRIORITY_HIGH;

HAL_DMA_SetConfigPeriphLinkedListCircularXfer(&hGPDMA1_CH1, &DMA_Node_SPDIFRX1_DT, &xfer_cfg_spdifrx1_dt_dma);

HAL_DMA_SetLinkedListXferFetchNodePort(&hGPDMA1_CH1, HAL_DMA_PORT0);



















/* Link the receive data DMA handle to the SPDIFRX handle */
HAL_SPDIFRX_SetDataDMA(&hSPDIFRX1, &hGPDMA1_CH1);

/* Start data reception in DMA mode */
HAL_SPDIFRX_ReceiveData_DMA(&hSPDIFRX1,
                            (uint32_t *) SpdifRxBuffer,
                            SPDIFRX_DATA_SIZE);

/* Abort the reception of data flow */
HAL_SPDIFRX_Data_Abort(&hSPDIFRX1);

/* Check the exact name of the SPDIFRX data
   DMA IRQ handler in the device startup file. */

/* SPDIFRX data complete callback */
void HAL_SPDIFRX_DataCpltCallback(hal_spdifrx_handle_t *hSPDIFRX1)
{
    data_cpt_occurred = 1;
}

Use case: HAL SPDIFRX control flow reception in DMA mode

Note

The following sequence diagrams describe the processing APIs for control reception in DMA mode. The configuration part has already been described in the polling use case above.

Sequence diagram

SPDIFRX HAL Receive control DMA

@startuml
hide footbox
participant "User Application" as p1
participant "<font color=green><b>HAL SPDIFRX</b></font>" as p2
participant "DMA" as p3
participant "NVIC" as p5
participant "Hardware" as p4

group Link DMA
  p1->p2: __HAL_LINKDMA(&hSPDIFRX1,\n               hdma_ctrl,\n               hdma_spdif_rx_cs)
end

group Start control DMA reception
  p1->p2: HAL_SPDIFRX_ReceiveCtrlFlow_DMA(&hSPDIFRX1,\n                                 pCtrlBuffer,\n                                 CTRL_SIZE)
  p2->p3: HAL_DMA_Start_IT(hdma_ctrl,\n                          src_addr, dest_addr,\n                          size)
end

group Control DMA complete
  p4-->p5: DMAx control complete interrupt
  p5->p3: HAL_DMA_IRQHandler(&hdma_spdif_rx_cs)
  p3->p2: XferCpltCallback()
  p2->p1: HAL_SPDIFRX_CxCpltCallback(&hSPDIFRX1)
  note over p1 #00FF00
  All control words have been received
  end note
end

group Stop the audio stream receive
  p1->p2: HAL_SPDIFRX_DMAStop(&hSPDIFRX1)
end
@enduml

Code snippet

HAL1

HAL2

#define SPDIFRX_CTRL_SIZE   24

uint32_t SpdifCxBuffer[SPDIFRX_CTRL_SIZE];
SPDIFRX_HandleTypeDef hSPDIFRX1;
DMA_NodeConfTypeDef NodeConfig;
DMA_NodeTypeDef Node_GPDMA1_Channel0;
DMA_QListTypeDef List_GPDMA1_Channel0;
DMA_HandleTypeDef handle_GPDMA1_Channel0;

volatile uint32_t ctrl_cpt_occurred = 0U;

/* Ensure that all required peripherals
   (SPDIFRX, GPIO, NVIC, DMA Clock etc...) are configured properly
/*
...
*/

NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_SPDIF_RX_CS;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0)

HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0)

HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0)

handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_HIGH_PRIORITY;
handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0)

HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0)

__HAL_LINKDMA(hSPDIFRX1, hdmaCsRx, handle_GPDMA1_Channel0);

/* Start control reception in DMA mode */
HAL_SPDIFRX_ReceiveCtrlFlow_DMA(&hSPDIFRX1,
                                (uint32_t *) SpdifCxBuffer,
                                SPDIFRX_CTRL_SIZE);

/* Stop the audio stream receive */
HAL_SPDIFRX_DMAStop(&hSPDIFRX1);

/* Check the exact name of the SPDIFRX control
   DMA IRQ handler in the device startup file. */

/* SPDIFRX control complete callback */
void HAL_SPDIFRX_CxCpltCallback(SPDIFRX_HandleTypeDef *hSPDIFRX1)
{
   ctrl_cpt_occurred = 1;
}
#define SPDIFRX_CTRL_SIZE   24

uint32_t SpdifCxBuffer[SPDIFRX_CTRL_SIZE];
hal_spdifrx_handle_t hSPDIFRX1;
hal_dma_handle_t hGPDMA1_CH0;
hal_dma_node_t DMA_Node_SPDIFRX1_CS;

volatile uint32_t control_cpt_occurred = 0U;

/* Ensure that all required peripherals
   (SPDIFRX, GPIO, NVIC, DMA Clock etc...) are configured properly
/*
...
*/



HAL_DMA_Init(&hGPDMA1_CH0, HAL_GPDMA1_CH0);
hal_dma_direct_xfer_config_t xfer_cfg_spdifrx1_cs_dma;
xfer_cfg_spdifrx1_cs_dma.request         = HAL_GPDMA1_REQUEST_SPDIFRX1_CS;
xfer_cfg_spdifrx1_cs_dma.direction       = HAL_DMA_DIRECTION_PERIPH_TO_MEMORY;
xfer_cfg_spdifrx1_cs_dma.src_inc         = HAL_DMA_SRC_ADDR_FIXED;
xfer_cfg_spdifrx1_cs_dma.dest_inc        = HAL_DMA_DEST_ADDR_INCREMENTED;
xfer_cfg_spdifrx1_cs_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_WORD;
xfer_cfg_spdifrx1_cs_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_WORD;
xfer_cfg_spdifrx1_cs_dma.priority        = HAL_DMA_PRIORITY_HIGH;

HAL_DMA_SetConfigPeriphLinkedListCircularXfer(&hGPDMA1_CH1, &DMA_Node_SPDIFRX1_CS, &xfer_cfg_spdifrx1_cs_dma)

HAL_DMA_SetLinkedListXferFetchNodePort(&hGPDMA1_CH1, HAL_DMA_PORT0)


















/* Link the receive control DMA handle to the SPDIFRX handle */
HAL_SPDIFRX_SetControlDMA(&hSPDIFRX1, &hGPDMA1_CH0);

/* Start control reception in DMA mode */
HAL_SPDIFRX_ReceiveCtrl_DMA(&hSPDIFRX1,
                            (uint32_t *) SpdifCxBuffer,
                            SPDIFRX_CTRL_SIZE);

/* Abort the reception of control flow */
HAL_SPDIFRX_Ctrl_Abort(&hSPDIFRX1);

/* Check the exact name of the SPDIFRX control
   DMA IRQ handler in the device startup file. */

/* SPDIFRX control complete callback */
void HAL_SPDIFRX_ControlCpltCallback(hal_spdifrx_handle_t *hSPDIFRX1)
{
    control_cpt_occurred = 1;
}